package com.hotel.front;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.SharedCache;
import com.StatusTitle;
import com.Util;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.labs.repackaged.org.json.JSONException;
import com.google.gson.Gson;
import com.hotel.BL.GenericLogic;
import com.hotel.BL.HouseKeepingLogic;
import com.hotel.BL.ReservationLogic;
import com.hotel.BL.RoomLogic;
import com.hotel.BL.RoomTypeLogic;

import data.CleaningStatus;
import data.HouseKeeping;
import data.Reservation;
import data.Room;
import data.RoomType;
import data.SubReservation;
import data.passingData.ResultData;
import data.passingData.RoomData;

@SuppressWarnings("serial")
public class RoomService extends HttpServlet {
	//http://localhost:8080/roomService?func=addRoom&roomName=room1&roomtypeString=vvvv&floorString=f&blockString=d&comment=g&cleaningStatusString=x&sortOrder=2
	//http://localhost:8080/roomService?func=editRoom&roomId=828&roomName=room1&roomtypeString=vvvv&floorString=f&blockString=d&comment=g&cleaningStatusString=x&sortOrder=2
	//http://localhost:8080/roomService?func=delRoom&roomId=828
	//http://localhost:8080/roomService?func=changeRoom&roomId=828
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		try{
			HttpSession session=req.getSession(true);	
			long hotelId = (Long) session.getAttribute("hotelId");
			String doClass = req.getParameter("func");
			if(doClass.equals("addRoom")){
				SharedCache.clearHotelCacheStartWith(hotelId,"RoomLogic");
				AddRoom(req,resp);
			}else if(doClass.equals("addMultiRoom")){
				SharedCache.clearHotelCacheStartWith(hotelId,"RoomLogic");
				AddMultiRoom(req,resp);
			}else if(doClass.equals("editRoom")){
				SharedCache.clearHotelCacheStartWith(hotelId,"RoomLogic");
				EditRoom(req,resp);
			}else if(doClass.equals("delRoom")){
				SharedCache.clearHotelCacheStartWith(hotelId,"RoomLogic");
				DeleteRoom(req,resp);
			}else if(doClass.equals("changeRoom")){
				ChangeStatus(req, resp);
			}else if(doClass.equals("changCleaningStatus")){
				ChangeCleaningStatus(req, resp);
			}else if(doClass.equals("getRoomName")){
				GetRoomName(req, resp);
			}else if(doClass.equals("getAllRooms")){
				GetAllRooms(req,resp);
			}else if(doClass.equals("getRoomsById")){
				GetRoomsById(req,resp);
			}else if(doClass.equals("getShowRooms")){
				GetShowRooms(req,resp);
			}else if(doClass.equals("loadFilter")){
				LoadFilter(req,resp);
			}else if(doClass.equals("load4Sort")){
				Load4Sort(req,resp);
			}else if(doClass.equals("editSortOrder")){
				EditSortOrder(req,resp);
			}else if(doClass.equals("ListRoomForHouseKeeping")){
				ListRoomForHouseKeeping(req,resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void AddRoom(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{		
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}	
		long hotelId = (Long) session.getAttribute("hotelId");
		
		String roomName = req.getParameter("roomname");
		String roomtypeString = req.getParameter("roomtype");
		String floorString = req.getParameter("floor");
		String blockString = req.getParameter("block");
		String comment = req.getParameter("description");
		CleaningStatus a = new GenericLogic(req,resp).GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.CleanRooms);
		String cleaningStatusString = String.valueOf(a.getId());

		new RoomLogic(req,resp).AddRoom(hotelId,roomName,roomtypeString,floorString,blockString,comment,cleaningStatusString,0);
		
		
		GetAllRooms(req, resp);
	}
	
	private void AddMultiRoom(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{		
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		long hotelId = (Long) session.getAttribute("hotelId");
		String roomNameList = req.getParameter("roomname");
		String roomtypeString = req.getParameter("roomtype");
		String floorString = req.getParameter("floor");
		String blockString = req.getParameter("block");
		String comment = req.getParameter("description");
		CleaningStatus a = new GenericLogic(req,resp).GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.CleanRooms);
		String cleaningStatusString = String.valueOf(a.getId());
		String[] splited = roomNameList.split(",");
		for(int i = 0; i < splited.length ; i++){
			new RoomLogic(req,resp).AddRoom(hotelId,splited[i],roomtypeString,floorString,blockString,comment,cleaningStatusString,0);
		}
		
		GetAllRooms(req, resp);
	}

	private void EditRoom(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		long roomId = Long.parseLong(req.getParameter("roomId"));
		String roomName = req.getParameter("roomname");
		String roomtypeString = req.getParameter("roomtype");
		String floorString = req.getParameter("floor");
		String blockString = req.getParameter("block");
		String comment = req.getParameter("description");
				
		new RoomLogic(req,resp).EditRoom(roomId,roomName,roomtypeString,floorString,blockString,comment);

		GetAllRooms(req, resp);

	}

	private void DeleteRoom(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}	
		long hotelId = (Long) session.getAttribute("hotelId");
		String roomIdList = req.getParameter("roomId");
		long roomamount = 0;
		List<String> list = new ArrayList<String>();
		ReservationLogic resLogic = new ReservationLogic(req,resp);
		RoomLogic roomLogic = new RoomLogic(req,resp);
		for(int i = 0; i < roomIdList.split(",").length ; i++){
			long ressize = resLogic.GetReservationByRoom(hotelId, Long.parseLong(roomIdList.split(",")[i])).size();
			roomamount += ressize;
			if(ressize !=0){
				list.add(roomLogic.GetRoom(Long.parseLong(roomIdList.split(",")[i])).getRoomName());
			}
		}
		if(roomamount == 0){
			for(int i=0;i<roomIdList.split(",").length ; i++){
				roomLogic.DeleteRoom(Long.parseLong(roomIdList.split(",")[i]));
			}
			GetAllRooms(req, resp);
		}else{
			
			HashMap<String,Object> returndata = new HashMap<String,Object>();
			returndata.put("data",null);
			returndata.put("cantdelete",list);
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(returndata));
		}
	}
	
	private void ChangeStatus(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}	
		long hotelId = (Long) session.getAttribute("hotelId");
		long roomId = Long.parseLong(req.getParameter("roomId"));
		RoomLogic roomLogic = new RoomLogic(req,resp);
		boolean isFoundUsed = roomLogic.CanChangeRoom(hotelId,roomId);
		HashMap<String,Object> data = new HashMap<String,Object>();
		if(isFoundUsed){
			data.put("data", roomLogic.GetRoom(roomId));
			data.put("canchange", false);
		}else{
			data.put("data", roomLogic.ChangeStatus(roomId));
			data.put("canchange", true);
		}
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(data));
	}
	
	private void ChangeCleaningStatus(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{
		Gson gson = new Gson();
		HttpSession session=req.getSession(true);
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		String[] roomIdString = req.getParameter("roomId").split(",");
		long cleanStatus = Long.parseLong(req.getParameter("cleanStatus"));
		RoomLogic roomLogic = new RoomLogic(req,resp);
		
		List<Room> result = new ArrayList<Room>();
		for(int i=0;i<roomIdString.length;i++){
			long roomId = Long.parseLong(roomIdString[i]);
			Room rs = roomLogic.ChangeCleaningStatus(roomId,cleanStatus);
			result.add(rs);
		}
		long hotelId = (Long) session.getAttribute("hotelId");
		SharedCache.clearHotelCacheStartWith(hotelId,"RoomLogic.GetRoom");
		String json = (result.size()==1)? gson.toJson(result.get(0)): gson.toJson(result);
		
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(json);
	}
	private void GetRoomName(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		long roomId = Long.parseLong(req.getParameter("roomId"));

		Object obj = new RoomLogic(req,resp).GetRoom(roomId);
		Gson gson = new Gson();

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(obj));
	}
	
	private void GetAllRooms(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);	
		long hotelId = (Long) session.getAttribute("hotelId");
		long offset = Long.parseLong(req.getParameter("offset"));
		double line = Double.parseDouble(req.getParameter("line"));
		long pointer = Long.parseLong(req.getParameter("pagePointer"));
		String byRoomType = req.getParameter("byRoomType");
		String byBlock = req.getParameter("byBlock");
		String byFloor = req.getParameter("byFloor");
		RoomLogic roomLogic = new RoomLogic(req,resp);
		List<Room> obj = roomLogic.GetAllRoom4AdminLimit(hotelId,offset,(long) line,byRoomType,byBlock,byFloor);
		double roomsize = roomLogic.AllRoomSize(hotelId, byRoomType, byBlock, byFloor);
		List<RoomData> objDataList = new ArrayList<RoomData>();
		
		for(int i =0;i< obj.size();i++){
			RoomData objData = new RoomData();
			objData.setBlockName(obj.get(i).getBlock().getTitle());
			if(obj.get(i).getFloorString()!= null ){
				objData.setFloorName(obj.get(i).getFloor().getTitle());
			}else{
				objData.setFloorName(null);
			}
			
			objData.setId(obj.get(i).getId());
			objData.setRoomName(obj.get(i).getRoomName());
			objData.setRoomtypeName(obj.get(i).getRoomtype().getShortName());
			objData.setStatus(obj.get(i).isStatus());
			objDataList.add(objData);
		}
		
		double dataSize = roomLogic.GetAllRoom4Admin(hotelId).size();
		Gson gson = new Gson();
		HashMap<String,Object> data = new HashMap<String,Object>();
		data.put("dataAmount",dataSize);
		data.put("pageNumber",pointer);
		data.put("lineAmount", line);
		data.put("pageAmount", Math.ceil(roomsize/line));
		data.put("data", objDataList);
		data.put("byRoomtype", byRoomType);
		data.put("byBlock", byBlock);
		data.put("byFloor", byFloor);
		
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(data));
	}
	
	private void GetRoomsById(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);
		long hotelId = (Long) session.getAttribute("hotelId");
		long id = Long.parseLong(req.getParameter("id"));
		RoomLogic roomLogic = new RoomLogic(req,resp);
		List<Object> filter = roomLogic.loadFilter(hotelId);
		Room obj = roomLogic.GetRoom(id);
		Gson gson = new Gson();
		List<Object> data = new ArrayList<Object>();
		data.add(obj);
		data.add(filter);
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(data));
	}
	
	private void GetShowRooms(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session = req.getSession(true);
		long hotelId = 1;
		if (session.getAttribute("hotelId") != null)
			hotelId = (Long) session.getAttribute("hotelId");
		List<Room> obj = new RoomLogic(req,resp).GetAllRoom(hotelId);
		Gson gson = new Gson();

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(obj));
	}
	
	private void LoadFilter(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}	
		long hotelId = (Long) session.getAttribute("hotelId");
		List<Object> obj = new RoomLogic(req,resp).loadFilter(hotelId);
		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(obj));
	}
	
	private void Load4Sort(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		HttpSession session=req.getSession(true);
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}	
		long hotelId = (Long) session.getAttribute("hotelId");
		List<Object> obj = new ArrayList<Object>();
		List<RoomType> rmtypeList = new RoomTypeLogic(req,resp).GetAllRoomType(hotelId);
		List<List<Room>> roomAll = new ArrayList<List<Room>>();
		RoomLogic roomLogic = new RoomLogic(req,resp);
		for(int i =0;i<rmtypeList.size();i++){
			List<Room> room = roomLogic.GetRoom(hotelId,rmtypeList.get(i).getId());
			roomAll.add(room);
		}
		obj.add(rmtypeList);
		obj.add(roomAll);

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(obj));

	}
	
	private void EditSortOrder(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException, ServletException, EntityNotFoundException
	{	
		Gson gson = new Gson();
		String sessionCheck = Util.checkSessionEntity(req,resp);
		if(sessionCheck==null||sessionCheck.equals("")){
			resp.setContentType("text/plain; charset=UTF-8");
			resp.getWriter().println(gson.toJson(new ResultData(false)));
			return;
		}
		long id = Long.parseLong(req.getParameter("id"));
		long sortOrder = Long.parseLong(req.getParameter("sortOrder"));

		new RoomLogic(req,resp).EditSortOrder(id, sortOrder);

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(true));
	}
	
	private void ListRoomForHouseKeeping(HttpServletRequest req, HttpServletResponse resp) throws IOException{
		HttpSession session = req.getSession(true);
		long hotelId = 1;
		if (session.getAttribute("hotelId") != null)
			hotelId = (Long) session.getAttribute("hotelId");
		RoomLogic roomLogic = new RoomLogic(req,resp);
		HouseKeepingLogic hkLogic = new HouseKeepingLogic(req,resp);
		GenericLogic gLogic = new GenericLogic(req,resp);
		
		Date today = Util.GetOnlyDate(gLogic.ServerDateFromNightAudit(hotelId));
		Date yesterday = Util.addDays(today, -1);
		
		HashMap<String,List<Reservation>> resStatusByList = roomLogic.GetRoomReservationTodayStatusByList(hotelId);
		List<Reservation> resStatus = roomLogic.GetRoomReservationTodayStatus(resStatusByList);
		List<Reservation> resYesterday = roomLogic.GetRoomReservationYesterdayStatus(hotelId);
		List<HouseKeeping> houseKeepingList = hkLogic.GetCurrentHouseKeepingByHotelId(hotelId);
		
		List<Room> rooms = roomLogic.GetAllRoom(hotelId);
		List<HashMap<String,Object>> obj = new ArrayList<HashMap<String,Object>>();
		for(Room r: rooms)
		{
			HashMap<String,Object> hash = new HashMap<String,Object>();
			hash.put("id", r.getId());
			hash.put("roomName", r.getRoomName());
			hash.put("roomtypeId", r.getRoomtype().getId());
			hash.put("block", r.getBlockString());
			hash.put("floor", r.getFloorString());
			hash.put("cleaningStatusId", r.getCleaningStatusString());
			hash.put("status", GetRoomResStatus(hotelId,r,resStatus,today));
			hash.put("yesterday", GetRoomResStatus(hotelId,r,resYesterday,yesterday));
			hash.put("statusC", GetRoomStat(r,resStatusByList,today));
			
			String pref="";
			String staff="";
			for(HouseKeeping hk :houseKeepingList)
				if(hk.getRoomId() == r.getId())
				{
					pref = hk.getReference();
					staff = hk.getStaffId();
				}
			hash.put("preference", pref);
			hash.put("staff", staff);
			obj.add(hash);
		}
		Gson gson = new Gson();

		resp.setContentType("text/plain; charset=UTF-8");
		resp.getWriter().println(gson.toJson(obj));
	}
	private String GetRoomResStatus(long hotelId,Room r,List<Reservation> resStatus,Date d){
		for(Reservation res : resStatus){
			Room resRoom = getRoomFromReservation(res,d);
			if(resRoom.getId() == r.getId())
				return res.getReservationStatusString();
		}
		return "-1";
	}
	private Room getRoomFromReservation(Reservation res,Date d){
		List<SubReservation> s = res.getSubReservationList();
		if(s==null || s.size()==0) return res.getRoom();
		else
			for(int i=0;i<s.size();i++)
			{
				if(!d.before(s.get(i).getDate()) && d.before(s.get(i).getDateTo()))
					return s.get(i).getRoom();
			}
		return res.getRoom();
	}
	private String GetRoomStat(Room r,HashMap<String,List<Reservation>> list,Date d)
	{
		List<Reservation> checkin = list.get("checkIn");
		List<Reservation> occupied = list.get("occupied");
		List<Reservation> checkout = list.get("checkout");
		for(Reservation res : checkin){
			Room resRoom = getRoomFromReservation(res,d);
			if(resRoom.getId() == r.getId())
				return "checkIn";
		}
		for(Reservation res : occupied){
			Room resRoom = getRoomFromReservation(res,d);
			if(resRoom.getId() == r.getId())
				return "occupied";
		}
		for(Reservation res : checkout){
			Room resRoom = getRoomFromReservation(res,d);
			if(resRoom.getId() == r.getId())
				return "checkout";
		}
		return "-1";
	}
}
